feat(bundle): onchain.kind = "semantos-cell" — one anchor, two checks - #7
Merged
Merged
Conversation
Both systems can write to chain. Left alone an integrated request gets anchored twice: semantos publishes a verified result cell, Trinote publishes a Third Entry, and the same computation carries two marks at two costs with two ways to disagree. So semantos publishes and a Trinote bundle records evidence pointing at what it published. The division of labour is the point: semantos proves the transaction is in a block — BEEF/SPV inclusion Trinote proves the anchored cell describes THIS receipt — content binding Neither substitutes for the other. An included transaction committing somebody else's computation is not evidence about this one, and a perfectly bound cell that was never mined is not evidence at all. This side does the second and refuses to imply the first: the on-chain path checks the transaction exists and has an output at the stated index — which is what fails when a txid is invented — and records in the result that inclusion was checked by semantos, not here. `inclusionProofRef` keeps broadcast and inclusion apart. Null means submitted; a reference means inclusion was proven and someone else can recheck it. Holding a txid says a broadcast happened, which is a different claim from being in a block. The digest must equal `evidenceCommit()` in the semantos cartridge or the two sides commit to different things while believing they agree, so the vectors in tests/vectors/semantos-cell.vectors.json were GENERATED by running that TypeScript: 7 accepted objects with their digests and their exact canonical bytes, 12 refusals with their reason codes. 19/19 agree. That check earned itself immediately — it found the semantos side accepting a negative vout in `evidenceCommit()` while its constructor refused one. Fixed upstream rather than matched here.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Phase 4's Trinote half. The semantos side has had
anchor-evidence.tsfor a while; thisis the end that consumes it.
Why a fourth bundle kind
Both systems can write to chain. Left alone an integrated request gets anchored twice —
semantos publishes a verified result cell, Trinote publishes a Third Entry — so the same
computation carries two marks, at two costs, with two ways to disagree.
So semantos publishes, and a Trinote bundle records evidence pointing at what it published.
Neither substitutes for the other. An included transaction that commits somebody else's
computation is not evidence about this one; a perfectly bound cell that was never mined is
not evidence at all.
What this side refuses to imply
The on-chain path could have returned
ok: trueand looked complete. It doesn't. It checkswhat it can honestly check — the transaction exists and really has an output at the stated
index, which is what fails when a txid is invented — and then records
semantosCell.inclusionCheckedBy: "semantos (BEEF/SPV); Trinote verifies content binding only". An auditor who reads this result should not come away thinking inclusion was provenhere.
modelBindingHashgets the same treatment: shape-checked and committed, never recomputed,because this side has nothing to derive it from.
evidence_binds_receipttakes it as anoptional argument that means "not checked here" — never "checked and passed".
Broadcast is not inclusion
inclusionProofRefis null for submitted, a reference for confirmed. Holding a txid says abroadcast happened, which is a different claim from the transaction being in a block. An
empty string is refused —
nullalready means "no proof", and two spellings of one claimare two digests.
The vectors are the real content
evidence_commithere must equalevidenceCommit()in the semantos cartridge, or bothsides commit to different things while believing they agree. So
tests/vectors/semantos-cell.vectors.jsonwas generated by running that TypeScript:bytes is the check that says the encoders agree; a matching digest alone could be a
collision
not a log message: a caller that branches on it must behave the same whichever
implementation it reached
19/19 agree.
It earned itself on the first run — it found the semantos side accepting
vout: -1inevidenceCommit()whileanchorEvidence()refused it. Fixed upstream (3cec4d8donfix/verifier-signature-into-main) rather than matched here, along with boundinginclusionProofRef. Nothing has been anchored under this kind yet, so tightening costsnothing now and would be a break later.
Verified
492 passed, 107 skipped— 36 of them new. The 2 failures intest_bonsai35_optimization_matrix.pyreproduce unchanged onmainin the sameenvironment. TypeScript side:
244 pass, 0 failin an isolated clone at3cec4d8d.